package com.yaodian100.ec.adlog.service.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.common.dao.ObjectDao;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.ec.adlog.entity.AdLog;
import com.yaodian100.ec.adlog.entity.AdLogDaily;
import com.yaodian100.ec.adlog.service.AdLogService;

/**
 * 
 * @author apple.chang
 * 
 */
public class AdLogServiceImpl extends DomainServiceImpl<AdLog> implements AdLogService {

	protected final Logger logger = LoggerFactory.getLogger(getClass());
	private ObjectDao<AdLogDaily> adLogDailyDao;
	private Map<String, AdLog> adLogs = new HashMap<String, AdLog>();

	@Override
	@Transactional(readOnly = false)
	public AdLogDaily saveAdLogDaily(AdLogDaily adLogDaily) throws Exception {
		adLogDaily = getAdLogDailyDao().save(adLogDaily);
		return adLogDaily;
	}

	public ObjectDao<AdLogDaily> getAdLogDailyDao() {
		return adLogDailyDao;
	}

	public void setAdLogDailyDao(ObjectDao<AdLogDaily> adLogDailyDao) {
		this.adLogDailyDao = adLogDailyDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.adlog.service.AdLogService#addAdLog(com.yaodian100.ec.adlog.entity.AdLog)
	 */
	@Override
	public void addAdLog(AdLog adLog) {
		synchronized (adLogs) {
			String key = adLog.getClientIp() + "_" + adLog.getChannelId() + "_" + adLog.getLogDate();
			logger.debug("AdLogServiceImpl:{}", key);
			if (adLogs.get(key) == null) {
				adLogs.put(key, adLog);
			} else {
				adLogs.get(key).setClickCount(adLogs.get(key).getClickCount() + 1);
			}
		}
	}

	@Transactional(readOnly = false)
	public void mapToDB(AdLog newAdLog) {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("channelId", newAdLog.getChannelId());
		criteria.addEq("logDate", newAdLog.getLogDate());
		criteria.addEq("clientIp", newAdLog.getClientIp());
		logger.debug("AdLogServiceImpl {}/{}/{}:",
				new Object[] { newAdLog.getChannelId(), newAdLog.getClientIp(), newAdLog.getLogDate() });
		List<AdLog> adLogList = getList(0, 1, criteria, null);
		try {
			if (null != adLogList && adLogList.size() > 0) {
				AdLog oldAdLog = adLogList.get(0);
				oldAdLog.setClickCount(oldAdLog.getClickCount() + newAdLog.getClickCount());
				update(oldAdLog);
			} else {
				save(newAdLog);
			}
		} catch (Exception e) {
			logger.error("AdLogServiceImpl error{}:" + e.getMessage());
		}
	}

	@Transactional(propagation = Propagation.NEVER)
	public void scheduleJob() {
		synchronized (adLogs) {
			boolean hasError = false;
			Iterator<AdLog> it = adLogs.values().iterator();
			while (it.hasNext()) {
				AdLog newAdLog = it.next();
				try {
					mapToDB(newAdLog);
					it.remove();
				} catch (Exception e) {
					logger.error("channelId:" + newAdLog.getChannelId() + ",clientIp:" + newAdLog.getClientIp(), e);
					hasError = true;
				}
			}

			try {
				if (hasError) {
					Thread.sleep(1000);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}